package com.spring.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.spring.annotation.*;


/**
 *  @author: zheng
 *  @Date: 2020-06-05 22:56
 *  @Description:反射工具类
 */
public class ReflectionUtils {

    private ReflectionUtils(){}

    public static void setObject(Field field, Object object, Object value) throws IllegalAccessException {
        boolean accessible = true;
        if(!field.canAccess(object)){
            accessible = false;
            field.setAccessible(true);
        }

        field.set(object,value);

        if(!accessible)
            field.setAccessible(false);
    }

    public static <A>Class<A> getAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) throws Exception{
        Class<A> resultAnnotionClass = null;

        Annotation[] annotations = clazz.getAnnotationsByType(annotationClass);
        if(annotations == null || annotations.length == 0){
            Annotation[] rawAnnotations = clazz.getAnnotations();

            for(Annotation a : rawAnnotations){
                InvocationHandler handler = Proxy.getInvocationHandler(a);
                Field field = handler.getClass().getDeclaredField("type");
                field.setAccessible(true);
                Class<A> clz = (Class<A>) field.get(handler);
                if (clz.isAnnotationPresent(annotationClass)) {
                    annotations = clz.getAnnotationsByType(annotationClass);
                    if(annotations.length > 0){
                        resultAnnotionClass = clz;
                    }
                }
            }
        }else{
            resultAnnotionClass = (Class<A>)annotationClass;
        }

        return resultAnnotionClass;
    }

    public static String getBeanValue(Class<?> clazz){
        String value = null;

        if(clazz.isAnnotationPresent(Component.class)){
            value = clazz.getAnnotation(Component.class).value();
        }else if(clazz.isAnnotationPresent(Service.class)){
            value = clazz.getAnnotation(Service.class).value();
        } else if(clazz.isAnnotationPresent(Repository.class)){
            value = clazz.getAnnotation(Repository.class).value();
        }

        return value;
    }

    public static Method getMethodOfObject(Object object, String methodName){
        Method[] declaredMethods = object.getClass().getDeclaredMethods();
        for(Method m :declaredMethods){
            if(methodName.equals(m.getName())){
                return m;
            }
        }

        return null;
    }

}